package com.kellycheung.chicken_go_go;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.UUID;

import org.json.JSONObject;

import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Parcelable;

public class GNetworkHandler {
	public enum GNRequestCode {
		NFC_ON(100), NFC_OFF(101)
		,BT_ON(200), BT_OFF(201)
		,WIFI_ON(300), WIFI_OFF(301)
		,WL_ON(400), WL_OFF(401)
		;
		
		private final int iVal;
		
		private GNRequestCode( int p_iVal ) { 
			this.iVal = p_iVal; 
		}
		
		public int getValue() {
			return this.iVal;
		}
	}
	
	abstract public class GNNetwork {
		protected GNetworkHandler gnHandler;
		protected Object adapter;
		
		public GNNetwork( GNetworkHandler p_gnh ) {
			try {
				this.gnHandler = p_gnh;
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNetwork" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		abstract public void initValue();
		
		public void destroy() {
			this.gnHandler = null;
			this.adapter = null;
		}
		
		abstract public Object getDefaultAdapter();
		
		abstract public boolean isAdapterEnabled();
		
		abstract public Intent requestEnableIntent();
		
		abstract public int requestOnCode();
		
		public boolean initAdapter() {
			try {
				if ( this.adapter == null ) {
					this.adapter = this.getDefaultAdapter();
				}
				
				if ( this.adapter == null ) {
					// TODO: Device not support
					throw new Exception( "Device not support" );
				}
				else if ( !this.isAdapterEnabled() ) {
					this.gnHandler.geMain.aApp.startActivityForResult( this.requestEnableIntent() , this.requestOnCode() );
					
					while ( !this.isAdapterEnabled() ) {
						Thread.sleep( 200 );
					}
				}
				
				return this.isAdapterEnabled();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNetwork.initAdapter" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		abstract public String getMacAddr();
		
		abstract public boolean connect( String p_sMacAddr );
		
		abstract public void pushMsg( String p_sTarget , JSONObject p_jo );
		
		abstract public String getMsg( String p_sSource );
	}
	
	public class GNBlueTooth extends GNetworkHandler.GNNetwork {
		public class GNBTListener extends Thread {
			protected GNBlueTooth gnbt;
			protected String sTargetMACAddr;
			protected boolean bConnected;
			
			public GNBTListener( GNBlueTooth p_gnbt ) {
				this.gnbt = p_gnbt;
				this.bConnected = false;
				
				this.start();
			}
			
			@Override
			public void run() {
				String macAddr;
				BluetoothServerSocket btssSocket;
				BluetoothSocket btsSocket;
				
				try{
					do {
						if ( !this.receivedBTMsg() ) {
							btssSocket = ((BluetoothAdapter)this.gnbt.adapter).listenUsingInsecureRfcommWithServiceRecord( this.gnbt.gnHandler.geMain.sPackageName , UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" ) ); //.createInsecureRfcommSocketToServiceRecord( UUID.fromString(this.gnHandler.geMain.sPackageName) );
							btsSocket = btssSocket.accept();
							
							if ( this.sTargetMACAddr == null || this.sTargetMACAddr.equals( "" ) ) {
								macAddr = btsSocket.getRemoteDevice().getAddress();
							}
							else {
								macAddr = this.sTargetMACAddr;
							}
							
							if ( btsSocket.getRemoteDevice().getAddress().equals( macAddr ) ) {
								this.gnbt.hmPeers.put( macAddr , new GNBlueTooth.GNBTPeer( this.gnbt , btsSocket ) );
								
								this.gnbt.bIsServerSide = true;
								
								this.gnbt.bIsAnyConnected = ( this.gnbt.bIsAnyConnected || btsSocket.isConnected() );
								
								this.gnbt.listenCallback();
								
								this.bConnected = btsSocket.isConnected(); 
							}
						}
						else {
							this.bConnected = true;
						}
					} while ( !this.bConnected );
		        } catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTListener.run" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public boolean receivedBTMsg() {
				try {
					String sMsg;
					
					if ( this.gnbt.isAnyConnectionCreated() ) {
						for ( String sMacAddr : this.gnbt.getLinkedMACAddr() ) {
							sMsg = this.gnbt.getMsg( sMacAddr );
							
							if ( sMsg != null && sMsg.length() > 0 ) {
								JSONObject joMsg = new JSONObject( sMsg );
								
								if ( joMsg != null && joMsg.has( "BTConnected" ) && joMsg.get( "BTConnected" ).toString().equals( "true" ) ) {
									this.gnbt.pollMsg( sMacAddr );
									
									return true;
								}
							}
						}
					}
		        } catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTListener.receivedBTMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
				
				return false;
			}
		}
		
		public class GNBTPeer extends Thread {
			protected final static int I_DELAY = 30;
			
			protected GNBlueTooth gnbt;
			protected BluetoothSocket btsSocket;
			
			protected LinkedList<String> qMsg;
			
			protected int iDelayCnt;
			
			public GNBTPeer( GNBlueTooth p_gnbt , BluetoothSocket p_btSocket ) {
				try {
					this.gnbt = p_gnbt;
					this.btsSocket = p_btSocket;
					this.qMsg = new LinkedList<String>();
					this.iDelayCnt = 0;
					
					this.start();
		        } catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public void destroy() {
				try {
					this.disconnect();
					if ( this.qMsg != null ) {
						this.qMsg.clear();
						this.qMsg = null;
					}
					
					this.btsSocket = null;
					this.gnbt = null;
		        } catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.destroy" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public void pushMsg( JSONObject p_jo ) {
				try {
					if ( this.btsSocket.isConnected() ) {
						try {
							this.btsSocket.getOutputStream().write( p_jo.toString().getBytes() );
						} catch ( IOException p_ioe ) {
							// TODO Auto-generated catch block
							this.disconnect( true );
						}
						
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.pushMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public boolean isConnected() {
				try {
					if ( this.btsSocket != null ) {
						return this.btsSocket.isConnected();
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.isConnected" );
					GameUtil.ErrorHandler( this , p_e );
				}
				
				return false;
			}
			
			@Override
			public void run() {
				try{
					while( this.isConnected() ) {
						this.iDelayCnt++;
						
						if ( iDelayCnt > GNBTPeer.I_DELAY ) {
							this.readMsg();
							this.iDelayCnt = 0;
						}
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.run" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public String getMsg() {
				try{
					if ( this.qMsg != null && this.qMsg.size() > 0 ) {
						return this.qMsg.peek();
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.getMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
				
				return null;
			}
			
			public String pollMsg() {
				try {
					if ( this.qMsg != null && this.qMsg.size() > 0 ) {
						return this.qMsg.poll();
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.pollMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
				
				return null;
			}
			
			public void pollAllMsg() {
				try {
					this.qMsg.clear();
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.pollAllMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public void readMsg() {
				try {
					byte[] bData = new byte[1024];
					int len = 0;
					
					if ( this.isConnected() ) {
						try {
							len = this.btsSocket.getInputStream().read( bData );
						} catch ( IOException p_ioe ) {
							// TODO Auto-generated catch block
							this.disconnect( true );
						}
						
						if ( len > 0 ) {
							this.qMsg.add( new String( bData , 0 , len ) );
						}
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.readMsg" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
			
			public void disconnect() {
				this.disconnect( false ); 
			}
			
			public void disconnect( boolean p_bErr ) {
				try {
					if ( this.isConnected() ) {
						if ( !p_bErr ) {
							this.pushMsg( new JSONObject().put( "Disconnect" , this.gnbt.getMacAddr() ) );
						}
						
						this.btsSocket.getInputStream().close();
						this.btsSocket.getOutputStream().close();
						this.btsSocket.close();
						
						this.btsSocket = null;
					}
				} catch ( Exception p_e ) {
					// TODO Auto-generated catch block
					GameUtil.LogMsg( this , "GNBTPeer.disconnect" );
					GameUtil.ErrorHandler( this , p_e );
				}
			}
		}
		
		protected HashMap<String, GNBTPeer> hmPeers;
		
		protected ButtonFunction cCallback;
		
		protected boolean bIsServerSide;
		protected String sServerMACAddr;
		protected boolean bIsAnyConnected;
		
		public GNBlueTooth( GNetworkHandler p_gnh ) {
			super( p_gnh );
			
			this.initValue();
		}
		
		@Override
		public void destroy() {
			try {
				this.disconnect();
				
				if ( this.hmPeers != null ) {
					for ( GNBTPeer gnbtp : this.hmPeers.values() ) {
						gnbtp.destroy();
					}
					
					this.hmPeers.clear();
					this.hmPeers = null;
				}
				
				this.cCallback = null;
				
				super.destroy();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.destroy" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		@Override
		public void initValue() {
			try {
				this.hmPeers = new HashMap<String, GNBTPeer>();
				this.bIsServerSide = false;
				this.sServerMACAddr = "";
				this.bIsAnyConnected = false;
				this.cCallback = null;
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.initValue" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public BluetoothAdapter getDefaultAdapter() {
			try {
				return BluetoothAdapter.getDefaultAdapter();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.getDefaultAdapter" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public boolean isAdapterEnabled() {
			try {
				if ( this.adapter == null ) {
					return false;
				}
				
				return ((BluetoothAdapter)this.adapter).isEnabled();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.isAdapterEnabled" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		public Intent requestEnableIntent() {
			try {
				return new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.requestEnableIntent" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public int requestOnCode() {
			return GNRequestCode.BT_ON.getValue();
		}
		
		public String getMacAddr() {
			try {
				if ( this.adapter == null ) {
					return null;
				}
				
				return ((BluetoothAdapter)this.adapter).getAddress();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.getMacAddr" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public boolean connect( String p_sBTMacAddr ) {
			try {
				BluetoothSocket btsSocket;
				
				if ( this.adapter == null ) {
					return false;
				}
				
				btsSocket = ((BluetoothAdapter)this.adapter).getRemoteDevice( p_sBTMacAddr ).createInsecureRfcommSocketToServiceRecord( UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" ) );
				btsSocket.connect();
				
				this.hmPeers.put( p_sBTMacAddr , new GNBTPeer( this , btsSocket ) );
				this.sServerMACAddr = p_sBTMacAddr;
				this.bIsAnyConnected = ( this.bIsAnyConnected || btsSocket.isConnected() );
				
				this.cCallback.call();
				
				return btsSocket.isConnected();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.connet" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		public boolean isConnected() {
			try {
				if ( !this.bIsServerSide ) {
					return this.isConnected( this.sServerMACAddr );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.isConnected" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		public boolean isConnected( String p_sBTMacAddr ) {
			try {
				if ( this.hmPeers.containsKey( p_sBTMacAddr ) ) {
					return this.hmPeers.get( p_sBTMacAddr ).isConnected();
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.isConnected(String)" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		public void pushMsg( JSONObject p_jo ) {
			try {
				if ( this.bIsServerSide ) {
					for ( String sTarget : this.getLinkedMACAddr() ) {
						this.pushMsg( sTarget , p_jo );
					}
				}
				else {
					this.pushMsg( this.sServerMACAddr , p_jo );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.pushMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void pushMsg( String p_sTarget , JSONObject p_jo ) {
			try {
				if ( this.hmPeers != null ) {
					this.hmPeers.get( p_sTarget ).pushMsg( p_jo );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.pushMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public String getMsg() {
			try {
				if ( !this.bIsServerSide ) {
					return this.getMsg( this.sServerMACAddr );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.getMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return "";
		}
		
		public String pollMsg() {
			try {
				if ( !this.bIsServerSide ) {
					return this.pollMsg( this.sServerMACAddr );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.pollMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return "";
		}
		
		public void pollAllMsg() {
			try {
				if ( !this.bIsServerSide ) {
					this.pollAllMsg( this.sServerMACAddr );
				}
				else {
					for ( String sMACAddr : this.getLinkedMACAddr() ) {
						this.pollAllMsg( sMACAddr );
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.pollAllMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public String getMsg( String p_sSource ) {
			return this.hmPeers.get( p_sSource ).getMsg();
		}
		
		public String pollMsg( String p_sSource ) {
			return this.hmPeers.get( p_sSource ).pollMsg();
		}
		
		public void pollAllMsg( String p_sSource ) {
			this.hmPeers.get( p_sSource ).pollAllMsg();
		}
		
		public void listenConnection() {
			try {
				new GNBTListener( this );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.listenConnection" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void listenCallback() {
			String[] sParm;
			try {
				sParm =  new String[] { ( this.bIsServerSide ? "true" : "false" ) };
				
				this.cCallback.setParm( sParm );
				this.cCallback.call();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.listenCallback" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		/*public boolean listenConnection( String p_sBTMacAddr ) {
			try {
				String macAddr;
				BluetoothServerSocket btssSocket;
				BluetoothSocket btsSocket;
				
				btssSocket = ((BluetoothAdapter)this.adapter).listenUsingInsecureRfcommWithServiceRecord( this.gnHandler.geMain.sPackageName , UUID.fromString( "00001101-0000-1000-8000-00805F9B34FB" ) ); //.createInsecureRfcommSocketToServiceRecord( UUID.fromString(this.gnHandler.geMain.sPackageName) );
				btsSocket = btssSocket.accept();
				
				if ( p_sBTMacAddr.equals( "" ) ) {
					macAddr = btsSocket.getRemoteDevice().getAddress();
				}
				else {
					macAddr = p_sBTMacAddr;
				}
				
				if ( btsSocket.getRemoteDevice().getAddress().equals( macAddr ) ) {
					this.hmPeers.put( macAddr , new GNBTPeer( this , btsSocket ) );
					
					this.bIsServerSide = true;
					
					this.bIsAnyConnected = ( this.bIsAnyConnected || btsSocket.isConnected() );
					
					this.cCallback.setParm( new String[] { "true" } );
					
					return btsSocket.isConnected();
				}
				else {
					
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.listenConnection" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}*/
		
		public String[] getLinkedMACAddr() {
			String[] sLinkedMacAddr = null;
			
			try {
				int iCnt = 0;
				
				if ( this.adapter != null ) {
					if ( this.hmPeers != null ) {
						sLinkedMacAddr = new String[this.hmPeers.size()];
						for ( String sTarget : this.hmPeers.keySet() ) {
							sLinkedMacAddr[iCnt] = sTarget;
							iCnt++;
						}
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.getLinkedMACAddr" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return sLinkedMacAddr;
		}
		
		public boolean isAnyConnectionCreated() {
			return this.bIsAnyConnected;
		}
		
		public void disconnect() {
			try {
				if ( this.isAnyConnectionCreated() ) {
					for ( String sTarget : this.hmPeers.keySet() ) {
						this.disconnect( sTarget );
					}
					
					if ( this.hmPeers.isEmpty() ) {
						this.initValue();
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.disconnect" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void disconnect( String p_sTarget ) {
			try {
				GNBTPeer gnbtPeer;
				
				if ( this.isConnected( p_sTarget ) ) {
					gnbtPeer = this.hmPeers.get( p_sTarget );
					
					gnbtPeer.disconnect();
					
					this.hmPeers.remove( gnbtPeer );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNBlueTooth.disconnect(String)" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
 	}
	
	public class GNNFC extends GNetworkHandler.GNNetwork {
		protected PendingIntent piNFCPendInt;
		protected IntentFilter[] ifaNFC;
		protected NdefMessage nmNFCMsg;
		//protected ButtonFunction cCallback;
		
		protected String writeJSONStr;
		protected String readJSONStr;
		protected boolean bIsMsgPush;
		
		public GNNFC( GNetworkHandler p_gnh ) {
			super( p_gnh );
			
			this.initValue();
		}
		
		@Override
		public void destroy() {
			try {
				if ( this.piNFCPendInt != null ) {
					this.piNFCPendInt.cancel();
					this.piNFCPendInt = null;
				}
				
				if ( this.ifaNFC != null ) {
					this.ifaNFC = null;
				}
				
				if ( this.nmNFCMsg != null ) {
					this.nmNFCMsg = null;
				}
				
				//this.cCallback = null;
				
				super.destroy();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.destroy" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		@Override
		public void initValue() {
			try {
				this.piNFCPendInt = null;
				this.ifaNFC = null;
				this.writeJSONStr = "";
				this.readJSONStr = "";
				this.nmNFCMsg = null;
				this.bIsMsgPush = false;
				//this.cCallback = null;
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.destroy" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public NfcAdapter getDefaultAdapter() {
			try {
				return NfcAdapter.getDefaultAdapter( this.gnHandler.geMain.aApp );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.getDefaultAdapter" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public boolean isAdapterEnabled() {
			try {
				if ( this.adapter == null ) {
					return false;
				}
				
				return ((NfcAdapter)this.adapter).isEnabled();
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.isAdapterEnabled" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return false;
		}
		
		public Intent requestEnableIntent() {
			try {
				return new Intent( android.provider.Settings.ACTION_WIRELESS_SETTINGS );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.requestEnableIntent" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public int requestOnCode() {
			return GNRequestCode.NFC_ON.getValue();
		}
		
		public String getMacAddr() {
			return null;
		}
		
		public boolean connect( String p_sMacAddr ) {
			if ( this.adapter != null ) {
				return true;
			}
			
			return false;
		}
		
		public void pushMsg( String p_sTarget , JSONObject p_jo ) {
			if ( this.adapter == null ) {
				return;
			}
		}
		
		public String getMsg( String p_sSource ) {
			if ( this.adapter == null ) {
				return null;
			}
			
			return null;
		}
		
		public void setNFCMsg( String[][] p_sKeyValue ) {
			try {
				if ( this.initAdapter() && this.bIsMsgPush == false ) {
					JSONObject json = this.gnHandler.getDefaultJSONHeader();
	
					for ( String[] sEntry : p_sKeyValue ) {
						json.put( sEntry[0] , sEntry[1] );
					}
					
					this.writeJSONStr = json.toString();
					this.nmNFCMsg = this.newNdefMessage( this.writeJSONStr );
					
					this.bIsMsgPush = this.nmNFCMsg == null ? true : false;
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.setNFCMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void onNewIntent( Intent p_i ) {
			try {
				if ( p_i != null ) {
					for ( String s : this.translateIntent( p_i ) ) {
						this.readJSONStr = s;
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.onNewIntent" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void onResume() {
			try {
				this.pushNFCMsg();
				((NfcAdapter)this.adapter).enableForegroundDispatch( this.gnHandler.geMain.aApp , this.piNFCPendInt , this.ifaNFC , null );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.onResume" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void onPause() {
			try {
				((NfcAdapter)this.adapter).disableForegroundDispatch( this.gnHandler.geMain.aApp );
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.onPause" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void pushNFCMsg() {
			try {
				if ( this.initAdapter() && this.writeJSONStr != null ) {
					Intent i = new Intent( this.gnHandler.geMain.aApp , this.gnHandler.geMain.aApp.getClass() ).addFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP );
					
					this.piNFCPendInt = PendingIntent.getActivity(
							this.gnHandler.geMain.aApp
							,0
							,i
							,PendingIntent.FLAG_UPDATE_CURRENT );
					
			        this.ifaNFC = new IntentFilter[] {
			        		new IntentFilter( NfcAdapter.ACTION_TAG_DISCOVERED )
			        		,new IntentFilter( NfcAdapter.ACTION_NDEF_DISCOVERED )
			        		,new IntentFilter( NfcAdapter.ACTION_TECH_DISCOVERED )
			        };
			        
					((NfcAdapter)this.adapter).setNdefPushMessage( this.nmNFCMsg , this.gnHandler.geMain.aApp );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.pushNFCMsg" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public NdefMessage newNdefMessage( String p_sMsg ) {
			try {
				if ( this.initAdapter() ) {
					byte[] langBytes = Locale.ENGLISH.getLanguage().getBytes( Charset.forName("US-ASCII") );
					byte[] textBytes = p_sMsg.getBytes( Charset.forName("UTF-8") );
					char status = (char)langBytes.length;
					byte[] data = new byte[ 1 + langBytes.length + textBytes.length ];
					data[0] = (byte)status;
					System.arraycopy( langBytes , 0 , data , 1 , langBytes.length );
					System.arraycopy( textBytes , 0 , data , 1 + langBytes.length , textBytes.length );
					
					return new NdefMessage( new NdefRecord[] { new NdefRecord( NdefRecord.TNF_WELL_KNOWN , NdefRecord.RTD_TEXT , new byte[0] , data ) } );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.newNdefRecord" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public String parseNdefRecord( NdefRecord p_nrRecord ) {
			try {
				byte[] bPayload = p_nrRecord.getPayload();
				if ( bPayload != null && bPayload.length > 0 ) {
					int langCodeLen = bPayload[0] & 0077;
					
					return new String( bPayload , langCodeLen+1 , bPayload.length-langCodeLen-1, "UTF-8" );
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.parseNdefRecord" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return null;
		}
		
		public NdefMessage[] getNdefMessages( Intent p_i ) {
			// TODO Auto-generated method stub
			NdefMessage[] nmMsgs = null;
			
			try {
				if ( NfcAdapter.ACTION_NDEF_DISCOVERED.equals( p_i.getAction() ) 
						|| NfcAdapter.ACTION_TAG_DISCOVERED.equals( p_i.getAction() )
						|| NfcAdapter.ACTION_TECH_DISCOVERED.equals( p_i.getAction() ) ) {
					Parcelable[] pRawMsg = p_i.getParcelableArrayExtra( NfcAdapter.EXTRA_NDEF_MESSAGES );
					
					if ( pRawMsg != null ) {
						nmMsgs = new NdefMessage[ pRawMsg.length ];
						for ( int i = 0 ; i < pRawMsg.length ; i++ ) {
							nmMsgs[i] = (NdefMessage)pRawMsg[i];
						}
					}
					else {
						byte[] bEmpty = new byte[] {};
						NdefRecord nrRecord = new NdefRecord ( NdefRecord.TNF_UNKNOWN , bEmpty , bEmpty , bEmpty );
						NdefMessage nmMsg = new NdefMessage ( new NdefRecord[] { nrRecord } );
						nmMsgs = new NdefMessage[] { nmMsg };
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.getNdefMessages" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return nmMsgs;
		}
		
		public String[] translateIntent( Intent p_i ) {
			String[] sResult = null;
			
			try {
				NdefMessage[] nmMsgs = this.getNdefMessages( p_i );
				if ( nmMsgs != null ) {
					String[] sTmpArr = new String[nmMsgs.length];
					JSONObject json;
					String sTmp;
					int cnt = 0;
					
					for ( NdefMessage nmMsg : nmMsgs ) {
						for ( NdefRecord nrRecord : nmMsg.getRecords() ) {
							sTmp = this.parseNdefRecord( nrRecord );
							if ( sTmp != null ) {
								json = new JSONObject( sTmp );
								
								if ( this.gnHandler.validJSON( json ) ) {
									sTmpArr[cnt] = json.toString();
									cnt++;
								}
							}
						}
					}
					
					sResult = new String[cnt];
					for ( int i = 0 ; i < cnt ; i++ ) {
						sResult[i] = sTmpArr[i];
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.translateIntent" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return sResult;
		}
		
		public String getReadValue( String p_sKey ) {
			String sVal = "";
			
			try {
				if ( this.readJSONStr != null ) {
					if ( !p_sKey.equals( "" ) && !this.readJSONStr.equals( "" ) ) {
						JSONObject jo = new JSONObject( this.readJSONStr );
						
						if ( jo != null && jo.has( p_sKey ) ) {
							sVal = jo.get( p_sKey ).toString();
						}
					}
				}
			} catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GNNFC.getReadValue" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return sVal;
		}
	}
	
	protected GameEngine geMain;
	protected GNBlueTooth gnbtHandler;
	protected GNNFC gnnfcHandler;
	
	public GNetworkHandler( GameEngine p_ge ) {
		this.geMain = p_ge;
	}
	
	public void destroy() {
		try {
			if ( this.gnbtHandler != null ) {
				this.gnbtHandler.destroy();
				this.gnbtHandler = null;
			}
			
			if ( this.gnnfcHandler != null ) {
				this.gnnfcHandler.destroy();
				this.gnnfcHandler = null;
			}
			
			this.geMain = null;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.destroy" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public JSONObject getDefaultJSONHeader() {
		JSONObject json = null;
		
		try {
			json = new JSONObject();
			
			json.put( "PkgName" , this.geMain.sPackageName );
			json.put( "PkgVer" , this.geMain.sPackageVer );
			json.put( "DevId" , this.geMain.sDeviceId );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.getDefaultJSONHeader" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return json;
	}
	
	public boolean validJSON( JSONObject p_json ) {
		try {
			if ( p_json != null && p_json.get("PkgName") != null ) {
				if ( p_json.get("PkgName").equals( this.geMain.sPackageName ) 
						&& p_json.get("PkgVer").equals( this.geMain.sPackageVer ) ) {
					return true;
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.validJSON" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public boolean initBT() {
		try {
			this.gnbtHandler = new GNBlueTooth( this );
			
			return this.gnbtHandler.initAdapter();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.initBT" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public boolean initNFC() {
		try {
			this.gnnfcHandler = new GNNFC( this );
			
			return this.gnnfcHandler.initAdapter();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.initNFC" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public boolean connBTByNFCInit( ButtonFunction p_bfCallback ) {
		try {
			if ( this.initBT() && this.initNFC() ) {
				this.gnnfcHandler.setNFCMsg( new String[][] { 
					{ "BTMacAddr" , this.gnbtHandler.getMacAddr() }
					,{ "BTIsServer" , this.gnbtHandler.bIsServerSide ? "1" : "0" }
				} );
				
				this.gnnfcHandler.pushNFCMsg();
				//this.gnnfcHandler.cCallback = p_bfCallback;
				this.gnbtHandler.cCallback = p_bfCallback;
				this.gnbtHandler.listenConnection();
				
				return true;
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.connBTByNFCInit" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public void connBTByNFCConnect() throws Exception {
		try {
			String peerBTMacAdrr = this.gnnfcHandler.getReadValue( "BTMacAddr" );
			//String thisBTMacAdrr = this.gnbtHandler.getMacAddr();
			//boolean thisBTIsServer = this.gnbtHandler.bIsServerSide;
			//boolean peerBTIsServer = ( Integer.valueOf(this.gnnfcHandler.getReadValue( "BTIsServer" )) == 0 ? false : true );
			//boolean bIsServer = false;
			
			if ( this.gnbtHandler.isConnected( peerBTMacAdrr ) ) {
				this.gnbtHandler.pushMsg( new JSONObject().put( "BTConnected" , "true" ) );
				this.gnbtHandler.listenCallback();
			}
			else {
				this.gnbtHandler.connect( peerBTMacAdrr );
			}
			/*if ( !peerBTIsServer ) {
				if ( thisBTIsServer ) {
					bIsServer = true;
				}
				else if ( !peerBTMacAdrr.equals("") ) {
					if ( thisBTMacAdrr.compareTo( peerBTMacAdrr ) < 0 ) {
						bIsServer = true;
					}
				}
				
				if ( this.gnbtHandler.isConnected( peerBTMacAdrr ) ) {
					this.gnbtHandler.cCallback.call();
				}
				else {
					if ( bIsServer ) {
						this.gnbtHandler.listenConnection( peerBTMacAdrr );
					} else {
						this.gnbtHandler.connect( peerBTMacAdrr );
					}
					if ( !bIsServer ) {
					this.gnbtHandler.connect( peerBTMacAdrr );
					}
				}
			}
			else {
				if ( thisBTIsServer ) {
					GameUtil.LogMsg( this , "BT Error" );
					throw new Exception( "BT Error" );
				}
			}*/
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.connBTByNFCConnect" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void disconnect() {
		try {
			if ( this.gnbtHandler != null ) {
				this.gnbtHandler.disconnect();
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.disconnect" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void onNewIntent( Intent p_i ) {
		try {
			if ( this.gnnfcHandler != null ) {
				this.gnnfcHandler.onNewIntent( p_i );
				
				this.connBTByNFCConnect();
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.onNewIntent" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void onResume() {
		try {
			if ( this.gnnfcHandler != null ) {
				this.gnnfcHandler.onResume();
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.onResume" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void onPause() {
		try {
			if ( this.gnnfcHandler != null ) {
				this.gnnfcHandler.onPause();
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GNetworkHandler.onPause" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
}
